﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace BreukTrainer.Model
{
    delegate Breuk DelegateBreukenBewerking(Breuk b1, Breuk b2);
    class ProgrammeerbareBreukContainer : BreukContainer
    {
        String[] volgorde;

        public String[] Volgorde
        {
            get { return volgorde; }
            set { volgorde = value; }
        }
        public ProgrammeerbareBreukContainer(String[] volgorde)
        {
            this.volgorde = volgorde;

        }
        public ProgrammeerbareBreukContainer()
        {
        }



        /// <summary>
        /// Doet de bewerking, aangeduid door delegateBreukenBewerking op de hele breukenlijst.
        /// </summary>
        /// <param name="delegateBreukenBewerking">De bewerking</param>
        /// <returns>Het resultaat</returns>
        public Breuk doeBewerking(DelegateBreukenBewerking delegateBreukenBewerking)
        {
            Breuk temp = null;
            if (breuken.Count > 0)
            {
                temp = new Breuk(breuken[0].Teller, breuken[0].Noemer);
                for (int i = 1; i < breuken.Count; i++)
                {
                    temp = delegateBreukenBewerking(temp, Breuken[i]);
                }
            }
            return temp;

        }
        /// <summary>
        /// Doet de bewerking, aangeduid door delegateBreukenBewerking op de hele breukenlijst.
        /// Indien de lijst te klein is, beginnen we van voren af aan.
        /// </summary>
        /// <param name="delegateBreukenBewerking">De bewerking</param>
        /// <param name="aantal">Hoeveel bewerkingen</param>
        /// <returns></returns>
        public Breuk doeBewerking(DelegateBreukenBewerking delegateBreukenBewerking, int aantal)
        {
            while (aantal > breuken.Count)
            {
                breuken.AddRange(breuken.GetRange(0, breuken.Count));
            }
            breuken.RemoveRange(aantal, breuken.Count - aantal);
            Breuk temp = null;
            if (breuken.Count > 0)
            {
                temp = new Breuk(breuken[0].Teller, breuken[0].Noemer);
                for (int i = 1; i < breuken.Count; i++)
                {
                    temp = delegateBreukenBewerking(temp, Breuken[i]);
                }
            }
            return temp;

        }
        public Breuk doeBewerking( DelegateBreukenBewerking[] delegateBreukenBewerkingen, Breuk[] breukjes)
        {
            int i = 0;
            Breuk temp = new Breuk(breuken[0].Teller, breuken[0].Noemer);
            foreach (DelegateBreukenBewerking d in delegateBreukenBewerkingen)
            {
                temp = d(temp, Breuken[i++]);
            }
            temp.Vereenvoudig();    
            return temp;
        }
        public Breuk doeBewerkingMetVolgorde(DelegateBreukenBewerking[] delegateBreukenBewerkingen, Breuk[] breukjes, String[] operanden, String[] volgordes)
        {
            Breuk temp = null;
            int volgorde = 0;
            List<int> gebruikt = new List<int>();
            foreach (String s in volgordes)//bewerkingen volgorde afgaan
            {
                foreach (String op in operanden)//de opgave overlopen
                {
                    if (s == op && !gebruikt.Contains(volgorde))//een bewerking gevonden
                    {
                        if (temp == null)//eerste keer
                        {
                            temp = breukjes[volgorde];
                            temp = delegateBreukenBewerkingen[volgorde](temp, breukjes[volgorde + 1]);
                        }
                        else
                        {
                            temp = delegateBreukenBewerkingen[volgorde](temp, breukjes[volgorde + 1]);
                        }
                        gebruikt.Add(volgorde);
                    }
                    volgorde++;
                }
                volgorde = 0;
            }
            temp.Vereenvoudig();
            return temp;
        }

        public Breuk doeBewerking(out String output, DelegateBreukenBewerking[] delegateBreukenBewerkingen, String[] operanden)
        {
            int i = 0;
            output = "";
            Breuk temp = new Breuk(breuken[0].Teller, breuken[0].Noemer);
            output = output + temp.ToString() + " " + operanden[0] + " ";
            foreach (DelegateBreukenBewerking d in delegateBreukenBewerkingen)
            {
                i++;
                output = output + Breuken[i].ToString();

                if (!(i >= operanden.Length))
                {
                    output = output + " " + operanden[i] + " ";
                }
                temp = d(temp, Breuken[i]);
            }
            temp.Vereenvoudig();
            output = output + "= " + temp.ToString();

            return temp;
        }
        public Breuk doeBewerkingMetVolgorde(out String output, DelegateBreukenBewerking[] delegateBreukenBewerkingen, String[] operanden, String[] volgordes)
        {
            Breuk temp=null;
            int volgorde = 0;
            List<int> gebruikt = new List<int>();
            output = "";
            while (operanden.Length+1 > breuken.Count)
            {
                breuken.AddRange(breuken.GetRange(0, breuken.Count));
            }

            foreach (String s in volgordes)//bewerkingen volgorde afgaan
            {
                foreach (String op in operanden)//de opgave overlopen
                {

                    if (s == op&&!gebruikt.Contains(volgorde))//een bewerking gevonden
                    {
                        if (temp == null)//eerste keer
                        {
                            temp = breuken[volgorde];
                            output = output + temp.ToString() + " " + op + " " + breuken[volgorde + 1].ToString();
                            temp = delegateBreukenBewerkingen[volgorde](temp, breuken[volgorde + 1]);
                            
                        }
                        else
                        {
                            output = output+" " + op + " "+breuken[volgorde+1];
                            temp = delegateBreukenBewerkingen[volgorde](temp, breuken[volgorde + 1]);
                            
                        }
                        gebruikt.Add(volgorde);
                    }
                    volgorde++;
                }
                volgorde = 0;
            }
            temp.Vereenvoudig();
            output = output + "= " + temp.ToString();
            return temp;
        }


        public override String ToString()
        {
            StringBuilder uitvoer = new StringBuilder("\nLijst van de huidige breuken:\n");
            uitvoer.Append("\n\nVan klein naar groot: ");
            breuken.Sort(delegate(Breuk b1, Breuk b2) { return b1.CompareTo(b2); });
            breuken.ForEach(delegate(Breuk b) { uitvoer.Append(String.Format("{0}/{1} ", b.Teller, b.Noemer)); });

            uitvoer.Append("\nVan groot naar klein: ");
            breuken.Sort(delegate(Breuk b1, Breuk b2) { return b2.CompareTo(b1); });
            breuken.ForEach(delegate(Breuk b) { uitvoer.Append(String.Format("{0}/{1} ", b.Teller, b.Noemer)); });
            return uitvoer.ToString();
        }
    }
}
